Repository navigation
feat(kap-server): add remote control device management - #4169
Conversation
|
There was a problem hiding this comment.
🟡 Changes recommended
Pending operations can survive logout, malformed responses can silently discard devices, and outbound requests can hang indefinitely.
3 open findings
What changed in this PR
Adds native Remote Control device management to kap-server and cleans up Remote Control state during OAuth logout.
Changes:
- Adds cloud-backed device listing, renaming, deactivation, and deletion APIs.
- Caches cloud sessions and retries once after a 401.
- Disables Remote Control and clears sessions before logout.
| File | Description |
|---|---|
packages/remote-control/src/device-client.ts |
Implements device client and session caching. |
packages/remote-control/src/index.ts |
Exports the device client. |
packages/remote-control/test/remote-control.test.ts |
Tests device operations and session behavior. |
packages/kap-server/src/start.ts |
Instantiates the client and selects registration identity. |
packages/kap-server/src/routes/remoteControl.ts |
Adds device management routes. |
packages/kap-server/src/routes/registerApiV1Routes.ts |
Wires Remote Control dependencies into OAuth routes. |
packages/kap-server/src/routes/oauth.ts |
Cleans up Remote Control before logout. |
packages/kap-server/src/protocol/rest-remote-control.ts |
Defines device API schemas. |
packages/kap-server/test/remoteControl.test.ts |
Tests routes, logout ordering, and identity behavior. |
packages/kap-server/test/__snapshots__/apiSurface.snapshot.test.ts.snap |
Records the expanded API surface. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The share link's from query parameter was hardcoded to kimi_code_cli, so links created by the desktop app were mislabeled as CLI traffic. buildRemoteControlUrl now takes the source explicitly and RemoteControlOptions carries it as urlSource; kap-server threads hostIdentity.platform through, so desktop hosts produce from=kimi_code_desktop while CLI hosts keep from=kimi_code_cli.
…ctivated or deleted The device management routes only called the cloud API. When the target device is the machine itself, the local tunnel kept running: after the relay drops it, the client reconnects and re-registers, so the device came back online (or was recreated after a delete) and the local status never returned to off. After a successful cloud deactivate/delete of the current device, the routes now also disable the local tunnel manager.
Device removal is collapsed to a single deactivate verb: the desktop UI
deactivates devices instead of deleting them, so the DELETE
/remote-control/devices/{id} route and the device client's deleteDevice
go away before this API ever ships.
The enable route now returns the RemoteControlAlreadyRunningError holder (pid, local origin, device id, url, started_at) in the error envelope's details, documented with a details schema, so desktop can render a structured conflict state instead of the raw message.
The manager now surfaces the holder when its last enable error is an already-running lock conflict, and GET /remote-control returns it as a structured conflict field, so clients can present the conflict state proactively instead of parsing the error message.
…atus GET /remote-control now re-inspects the machine lock whenever the manager is off: a live holder is reported as the conflict even without a prior enable attempt in this process, and a stored conflict plus its error text are dropped once the holder's process is gone. Panel state refreshes such as after device deactivation now reflect reality.
…ce deactivation When the deactivated device is the machine's own and the lock is held by another live process (e.g. a CLI instance whose tunnel the relay is about to terminate with user_requested), the route now polls the lock for up to two seconds before responding, so a client's immediately following status read sees the settled conflict-free state.
…evice-management # Conflicts: # packages/kap-server/src/start.ts
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed43353053
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…ement' into feat/remote-control-device-management
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a638c64fa4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf9a27d328
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9f62801999
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
… sessions after logout
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1955b5dfc1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…telist device fields
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de8830eedf
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…out before tunnel teardown
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 34f23dd53f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 442aecffb8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ab76e38658
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d35a762085
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |


Requirement or Bug
Add kap-server APIs that let desktop manage Remote Control devices natively and clean up Remote Control sessions on logout.
Desktop companion: MoonshotAI/kimi-code-app#838
Bug Reproduction Steps
N/A
Root Cause
N/A
Code Changes
RemoteControlDeviceClientfor cloud device listing, rename, and deactivate operations without exposing OAuth tokens or cloud cookies to the renderer. There is intentionally no delete endpoint: deactivation takes a device offline and offline devices stay listed without consuming quota.clear()aborts in-flight requests.RemoteControlDeviceClientErroron malformed shapes instead of silently reporting an empty list.VALIDATION_FAILEDand cloud/network failures toINTERNAL_ERROR, without triggering the local auth-required flow.<productName>/<version>) instead of the historical hardcodedkimi-code/<server version>, and tags share URLs with the host platform (from=kimi_code_cli/kimi_code_desktop).conflict) and in the already-running error details, resolving the lock live on every status read so a dead holder clears automatically.startingcancellable:disable()during an in-flight start aborts the connect loop and releases the lock instead of waiting forever for a settle that may never come (relay unreachable), anddisable()now rejects when the tunnel close fails instead of swallowing the error intostatus.error.enable()/disable()calls are serialized through an internal queue, so a toggle queued behind a cancelled start is applied in order instead of being lost while both snapshot a staleoffstate.docs/{en,zh}/reference/server-api.md.loadOrCreateServerTokenfrom@moonshot-ai/kap-serverso hosts (e.g. the desktop app's embedded server) can provision the sharedserver.tokenthat Remote Control authentication requires, instead of replicating the private-file write logic.Behavior Changes and Affected Users
/api/v1/remote-control/devices*proxies the cloud device list/rename/deactivate APIs for authenticated local clientsclient_versionregistrationkimi-code/<version>kimi-code-cli/<version>, desktop registerskimi-code-desktop/<version>(CLI call sites share one app-level constant)VARCHAR(64), returned in the device list, used as a trace label; no parsing, version gating, or fingerprinting (device identity isdevice_id). Verified against the relay sourceRemoteControlManager.disable()during an in-flight startoff; the pendingenable()rejects with "disabled while starting"RemoteControlManager.disable()failurestatus.erroranddisable()resolveddisable()rejects on stop failuredisable()never throws (close()already guards)Affected modules and coverage:
packages/remote-control: exchange/cookie caching, 401 refresh and retry limit, OAuth slot selection,clear()invalidation and in-flight abort, request timeout, payload validation and field projection, manager start cancellation, disable failure, serialized toggles, and handshake abortion on close — 38 tests passed.packages/kap-server: device routes, alias validation, cloud error mapping, API surface snapshot, logout ordering/provider scoping/foreign-holder deactivation/start gating/serialization/respond-first teardown, registration identity, live conflict resolution, deactivate lock wait and in-flight start cancellation — 25 tests passed (full package 1436 passed, 1 skipped; the unrelatedGlobalSearchServicecase is flaky in parallel runs and passes standalone).apps/kimi-code: CLI web remote-control call sites and close-reason handling — 83 tests passed.pnpm --filter @moonshot-ai/remote-control run typecheck && pnpm --filter @moonshot-ai/kap-server run typecheckpassed.Checklist
No changeset was added at the requester's direction; the behavior changes are declared in the table above.
/approve).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.